package othello.players;

import java.awt.Color;
import java.util.Observable;
import othello.gui.IGui;
import othello.model.GameBoard;
import othello.model.GameState;
import othello.model.IBoard;
import othello.model.Action;
import othello.players.learnplayers.AbstractNeuralNetworkPlayer;
import othello.players.learnplayers.AbstractNeuralNetworkPlayer.BenchmarkState;
import java.util.List;
import java.util.ArrayList;

public abstract class AbstractPlayer implements IPlayer {
	protected final String name;
	protected IBoard board;
	protected Color color;
    protected boolean active = false;
    private PlayerResults playResults;
    private PlayerResults learnResults;
    private List<Action> trainingActions;

    protected AbstractPlayer(String name) {
    	this.name = name;
    	this.playResults = new PlayerResults();
    	this.learnResults = new PlayerResults();    	
    }
    
    @Override
    public boolean isActive() {
        return active;
    }
    
    @Override
    public void setActive(boolean active) {
        this.active = active;
    }
    
    public IBoard getBoard() {
        return board;
    }

    public void setBoard(IBoard board) {
        this.board = board;
    }    

    @Override
    public void setColor(Color color) {
    	this.color = color;
    }

    @Override
    public Color getColor() {
        return color;
    }

    @Override
    public String getName() {
        return IGui.colorName(getColor()) + "-" + name;
    }

    @Override
    public void joinBoard(IBoard board, Color color) {
        this.board = board;
        this.color = color;
    }

    @Override
    public void update (Observable obj, Object arg) {
        if (arg instanceof GameState){
            GameState s = (GameState) arg;
            if(GameState.ENDGAME == s) {
                endGame();
            }
            else if(((GameBoard) obj).getCurrentPlayerColor() == getColor()){
                 if(GameState.ENDTURN == s) {
                    endTurn();
                } else if(GameState.BEGINTURN == s) {
                    beginTurn();
                }
            }
            if(GameState.SAVETRAINING == s && this instanceof AbstractNeuralNetworkPlayer) {
            	((AbstractNeuralNetworkPlayer) this).saveWeights();
            }
        }
    }
    
    @Override
    public void won(BenchmarkState benchmarkState) {
    	if (benchmarkState == BenchmarkState.Training)
    		learnResults.won();
    	else
    		playResults.won();
    }
    
    @Override
    public void lost(BenchmarkState benchmarkState) {
    	if (benchmarkState == BenchmarkState.Training)
    		learnResults.lost();
    	else
    		playResults.lost();
    }
    
    @Override
    public void tied(BenchmarkState benchmarkState) {
    	if (benchmarkState == BenchmarkState.Training)
    		learnResults.tied();
		else
    		playResults.tied();
    }
    
    @Override
    public void resetPlayResults() {
    	playResults.reset();
    }
    
    @Override
    public void storeRatio() {
    	playResults.storeRatio();
    }
    
    @Override
    public void saveRatios() {
    	System.out.println("Learn results:");
    	learnResults.saveRatios(getName(),board.getRun()); // add run!
    	System.out.println();
    	System.out.println("Play (or benchmark) results:");
    	playResults.saveRatios(getName(),board.getRun());
    	System.out.println();
    }
    
    @Override
    public List<Action> getAvailableActions(IBoard brd) {
        ArrayList<Action> availableActions = new ArrayList<Action>();
    	for (int row = 0; row < 8; row++) {
            for (int col = 0; col < 8; col++) {
                if(brd.isValidMove(brd.getCurrentPlayerColor(), row, col)) {
                    availableActions.add(new Action(row, col));
                }
            }
        }        
        return availableActions;
    }   
    
}
